%! SmithDraw 1.1 % pour Smith DRAW par PAUTEX JF version non cmmerciale % % gsave 0 728 translate 1 -1 scale % %4.25 72 mul 5.9 72 mul translate 3.8 72 mul 5 72 mul translate % /Helvfont {/Helvetica findfont 5 scalefont setfont} def Helvfont /Symfont {/Symbol findfont 5 scalefont setfont} def % %* %* "Labels" are the numbers which index the R & X circles; "Lvalues" %* are the actual label values; "Regions", "Minordiv", and %* "Majordiv" define the boundaries and divisions of the various %* regions within with the same grid density is kept. %* [(0) (0.1) (0.2) (0.3) (0.4) (0.5) (0.6) (0.7) (0.8) (0.9) (1.0) (1.2) (1.4) (1.6) (1.8) (2.0) (3.0) (4.0) (5.0) (10) (20) (50)] /Labels exch def [0 0.1 0.2 0.3 0.4 0.5 0.6 0.7 0.8 0.9 1.0 1.2 1.4 1.6 1.8 2.0 3.0 4.0 5.0 10 20 50] /Lvalues exch def [ 0 0.2 0.5 1 2 5 10 20 50 ] /ZRegions exch def [ 0.01 0.02 0.05 0.1 0.2 1 2 10 ] /ZMinordiv exch def [ 5 5 2 2 5 5 5 5 ] /ZMajordiv exch def [ 0 1 2 4 10 20 50 ] /YRegions exch def [ 0.1 0.2 0.5 1 5 30 ] /YMinordiv exch def [ 5 5 2 6 2 1 ] /YMajordiv exch def /minorinc 0 def /majorinc 0 def /Unitradius 3.25 72 mul def % Radius of rho=1 circle % (also used for general scaling) /Coeffradius 3.375 72 mul def % Radius of angle circle /Waveradius 3.625 72 mul def % Radius of wavelength circle %***** r x RXtoUV v u %* %* Converts Z space (r + jx) to gamma space (u + jv) %* /RXtoUV { /xtmp exch def /rtmp exch def rtmp rtmp mul xtmp xtmp mul add rtmp 2 mul add 1 add /dtmp exch def rtmp rtmp mul xtmp xtmp mul add 1 sub dtmp div xtmp 2 mul dtmp div } def %***** r x AngR thetaR %* %* Finds the angle of the line from the center of the R=r circle to (r + jx) %* /AngR { /xa exch def /ra exch def ra xa RXtoUV exch ra ra 1 add div sub atan } def %***** r x AngX thetaX %* %* Finds the angle of the line from the center of the X=x circle to (r + jx) %* /AngX { /xa exch def /ra exch def ra xa RXtoUV 1 xa div sub exch 1 sub atan } def %***** u v radius ang1 ang2 Doarc - %* %* Guess. %* /Doarc { 5 -1 roll Unitradius mul 5 -1 roll Unitradius mul 5 -1 roll Unitradius mul 5 -2 roll arc stroke } def %***** r x1 x2 DrawRarc - %* %* Right again. %* /DrawRarc { /xx2 exch def /xx1 exch def /rr exch def rr dup 1 add div /u0 exch def /v0 0 def 1 rr 1 add div /radius exch def rr xx1 AngR /theta1 exch def rr xx2 AngR /theta2 exch def u0 v0 radius theta1 theta2 Doarc } def %***** x r1 r2 DrawXarc - %* %* Hey! 3 for 3! %* /DrawXarc { /rr2 exch def /rr1 exch def /xx exch def /u0 1 def 1 xx div /v0 exch def 1 xx div abs /radius exch def rr1 xx AngX /theta1 exch def rr2 xx AngX /theta2 exch def u0 v0 radius theta1 theta2 Doarc } def %***** Doblock %* %* Draws a grid block bounded by (r1 + jx1) and (r2 + jx2) %* /Doblock { /rtics 0 def r1 minorinc add minorinc r2 minorinc 2 div add { /r exch def rtics 1 add dup /rtics exch def majorinc mod 0 eq {0.5 setlinewidth} {0 setlinewidth} ifelse r x2 x1 DrawRarc r x1 neg x2 neg DrawRarc } for /xtics 0 def x1 minorinc add minorinc x2 minorinc 2 div add { /x exch def xtics 1 add dup /xtics exch def majorinc mod 0 eq {0.5 setlinewidth} {0 setlinewidth} ifelse x r1 r2 DrawXarc x neg r2 r1 DrawXarc } for } def %***** regions minordiv majordiv Doimmittance - %* %* Draws the R & X (or G & B) circles %* /Doimmittance { /Majordiv exch def /Minordiv exch def /Regions exch def 0 1 Minordiv length 1 sub {/index exch def Minordiv index get /minorinc exch def Majordiv index get /majorinc exch def 0 /r1 exch def % wings Regions index 1 add get /r2 exch def Regions index get /x1 exch def Regions index 1 add get /x2 exch def Doblock Regions index get /r1 exch def % trunk Regions index 1 add get /r2 exch def 0 /x1 exch def Regions index get /x2 exch def index 7 eq {majorinc 3 def} if % yukky hack Doblock } for 0.5 setlinewidth Unitradius neg 0 moveto Unitradius 0 lineto stroke 0 0 Unitradius 0 360 arc stroke 50 10000 0 DrawRarc 50 0 -10000 DrawRarc 50 0 10000 DrawXarc -50 10000 0 DrawXarc newpath 0 0 2 0 360 arc currentgray 1 setgray fill setgray 0 setlinewidth 0 0 2 0 360 arc stroke 0 0 0.25 0 360 arc stroke } def %***** x y label Dorightstring - %* %* Right-justifies "label" and writes it on a white background %* /Dorightstring { /lab exch def /yl exch def /xl exch def lab stringwidth pop /wid exch def newpath xl yl moveto wid neg 0 rlineto 0 5 rlineto wid 0 rlineto 0 -5 rlineto closepath currentgray 1 setgray fill xl yl moveto wid neg 1 rmoveto setgray lab show } def %***** x y label Doleftstring - %* %* Left-justifies "label" and writes it on a white background %* /Doleftstring { /lab exch def /yl exch def /xl exch def lab stringwidth pop /wid exch def newpath xl yl moveto wid 0 rlineto 0 5 rlineto wid neg 0 rlineto 0 -5 rlineto closepath currentgray 1 setgray fill xl yl 1 add moveto setgray lab show } def %***** - DoLabels - %* %* Writes all the numbers within the R-X area %* /DoLabels { 1 1 Lvalues length 1 sub { dup Labels exch get /label exch def Lvalues exch get /x exch def 0 x RXtoUV exch atan gsave rotate Unitradius 1 sub 1 label Dorightstring grestore 0 x neg RXtoUV exch atan 180 add gsave rotate Unitradius 1 sub neg 1 label Doleftstring grestore x 0 RXtoUV pop Unitradius mul neg gsave 90 rotate 1 add 2 exch label Doleftstring grestore } for 2 2 10 { dup Labels exch get /label exch def Lvalues exch get /x exch def x 1 RXtoUV Unitradius mul exch Unitradius mul exch gsave translate x 1 AngX 180 add rotate 1 1 label Doleftstring grestore x -1 RXtoUV Unitradius mul exch Unitradius mul exch gsave translate x -1 AngX rotate -1 1 label Dorightstring grestore 1 x RXtoUV Unitradius mul exch Unitradius mul exch gsave translate 1 x AngR rotate -1 1 label Dorightstring grestore 1 x neg RXtoUV Unitradius mul exch Unitradius mul exch gsave translate 1 x neg AngR 180 add rotate 1 1 label Doleftstring grestore } for } def %* %* Draws the R & X (impedance) circles %* /DoRX { ZRegions ZMinordiv ZMajordiv Doimmittance DoLabels } def %* %* Draws the G & B (admittance) circles in gray %* /DoGB { gsave currentdash [1 1] 0 setdash 180 rotate YRegions YMinordiv YMajordiv Doimmittance DoLabels setdash grestore } def %***** string radius radial Doperp - %* %* Writes "string" centered at the point which is "radial" units, along %* the angle "radial", from the center. %* /Doperp { gsave rotate 0 translate -90 rotate dup stringwidth pop 2 div neg 0 moveto show grestore } def %***** angle FindTCrad radius %* %* A messy hack which finds the distance from the (-1,0) to the %* coefficient angle circle. %* /FindTCrad {/th exch def th sin Unitradius mul Coeffradius div dup dup mul neg 1 add sqrt div 1 atan 180 th sub exch sub sin Coeffradius mul th sin div } def %***** Docoeffcircle %* %* Draws and labels the coefficient angle circle. %* /Docoeffcircle { 0 setlinewidth 0 setgray 0 0 Coeffradius 0 360 arc stroke gsave 0 2 178 { pop Coeffradius neg 0 moveto -2 0 rlineto stroke Coeffradius 0 moveto 2 0 rlineto stroke 2 rotate } for grestore /str 20 string def 20 10 170 { dup dup str cvs exch Coeffradius 3 add exch Doperp neg dup str cvs exch Coeffradius 3 add exch Doperp } for (180) Coeffradius 3 add 180 Doperp Symfont (\261) Coeffradius 3 add 181.5 Doperp Helvfont gsave Unitradius neg 0 translate 90 -1 1 {/thet exch def thet FindTCrad /TCrad exch def gsave thet rotate TCrad 0 moveto -3 0 rlineto stroke thet 10 ge thet 5 mod 0 eq and { TCrad 2 sub -4 moveto thet str cvs dup stringwidth pop neg 0 rmoveto show } if grestore gsave 180 thet sub rotate TCrad neg 0 moveto 3 0 rlineto stroke thet 10 ge thet 5 mod 0 eq and { TCrad neg 1 add -4 moveto thet neg str cvs show } if grestore } for grestore 0.5 setlinewidth 0 0 Coeffradius Waveradius add 2 div 0 360 arc stroke 0 setlinewidth Coeffradius 3 sub 0 moveto 3 0 rlineto stroke } def %***** Dowavecircle %* %* Draws and labels the wavelength circle. %* /Dowavecircle { /str 20 string def 0 setlinewidth 0 setgray 0 0 Waveradius 0 360 arc stroke /lstep 180 125 div def 1 1 250 {/ix exch def gsave ix lstep mul rotate Waveradius 2 add neg 0 moveto 4 0 rlineto stroke grestore ix 5 mod 0 eq ix 16 gt and { ix 250 eq {0} {ix} ifelse 500 div str cvs dup gsave ix lstep mul rotate Waveradius 7 sub neg 0 translate 90 rotate dup stringwidth pop 2 div neg 0 moveto show grestore gsave ix lstep mul neg rotate Waveradius 3 add neg 0 translate 90 rotate dup stringwidth pop 2 div neg 0 moveto show grestore } if } for 0.5 setlinewidth 0 0 Waveradius dup Coeffradius sub 2 div add 0 360 arc stroke 0 setlinewidth } def %* %* The following three procedures were stolen from the Adobe %* "Blue book". Together, they place a string along an arc. %* /pi 3.141592654 def /findhalfangle { stringwidth pop 2 div 2 xrad mul pi mul div 360 mul } def /outsideplacechar { /char exch def /halfangle char findhalfangle def gsave halfangle neg rotate rad 0 translate -90 rotate char stringwidth pop 2 div neg 0 moveto char show grestore halfangle 2 mul neg rotate } def %***** string pointsize centerangle radius outsidecircletext - /outsidecircletext { /rad exch def /centerangle exch def /ptsize exch def /str exch def /xrad rad ptsize 4 div add def gsave centerangle str findhalfangle add rotate str {/charcode exch def ( ) dup 0 charcode put outsideplacechar } forall grestore } def %***** Docircletext %* %* Draws all the text which is written along an arc. What a mess. %* /Docircletext { (ANGLE DU COEFFICIENT DE TRANSMISSION EN DEGRES) 5 0 Coeffradius 7 sub outsidecircletext (ANGLE DU COEFFICIENT DE REFLECTION EN DEGRES) 5 0 Coeffradius 3 add outsidecircletext (\320> LONGUEUR D'ONDE VERS LE GENERATEUR \320>) 5 166 Waveradius 3 add outsidecircletext (<\320 LONGUEUR D'ONDE VERS LA CHARGE <\320) 5 -166.5 Waveradius 7 sub outsidecircletext /a1 164 def /u1 a1 cos def /v1 a1 sin def /a2 108 def /u2 a2 cos def /v2 a2 sin def /r Unitradius 0.940 mul def newpath u1 r mul 1 sub v1 r mul 1 sub moveto u1 5 mul v1 5 mul rlineto 0 0 r 5 add a1 a2 arcn u2 5 mul neg u2 5 mul neg rlineto 0 0 r 1 sub a2 a1 arc closepath currentgray 1 setgray fill setgray (REACTANCE INDUCTIVE \(+jX/Zo\), \ OU SUSCEPTANCE CAPACITIVE \(+jB/Yo\)) 5 136 r outsidecircletext gsave 1 -1 scale newpath u1 r mul 1 sub v1 r mul 1 sub moveto u1 5 mul v1 5 mul rlineto 0 0 r 5 add a1 a2 arcn u2 5 mul neg u2 5 mul neg rlineto 0 0 r 1 sub a2 a1 arc closepath currentgray 1 setgray fill setgray grestore (REACTANCE CAPACITIVE \(-jX/Zo\), \ OU SUSCEPTANCE INDUCTIVE \(-jB/Yo\)) 5 -136 r outsidecircletext /u1 Unitradius 0.800 mul neg def (COMPOSANTE RESISTIVE \(R/Zo\), OU CONDUCTANCE \(G/Yo\)) dup stringwidth pop /u2 exch u1 add def newpath u1 -15 moveto u1 -10 lineto u2 -10 lineto u2 -15 lineto closepath currentgray 1 setgray fill setgray u1 1 add -14 moveto show 0 setgray } def %* %* These arrays define most of the nomograph lines. This was the %* fastest way to grind these out (no, really). The "...labels" array %* gives the values which should be placed along the axis; the "...divs" %* and "...breaks" define the distance between tics, and where the distance %* changes, respectively. %* /Swrlabels [1.1 1.2 1.4 1.6 1.8 2 2.5 3 4 5 10 20 40 100] def /Swrbreaks [1.05 1.2 3 4 5 10 20 40 100] def /Swrdivs [0.05 0.1 0.2 0.5 1 2 10 60] def /Dbslabels [1 2 3 4 5 6 8 10 15 20 30 40] def /Dbsbreaks [0.5 6 20 30 40] def /Dbsdivs [0.5 1 2 5] def /Attlabels [1 2 3 4 5 7 10 15] def /Attbreaks [0.2 5 10 15] def /Attdivs [0.2 0.5 1] def /Swllabels [1.1 1.2 1.3 1.4 1.6 1.8 2 3 4 5 10 20] def /Swlbreaks [1.02 1.2 1.4 2 3 5 10 20 50] def /Swldivs [0.02 0.05 0.1 0.2 0.5 1 5 30] def /Rldblabels [0 1 2 3 4 5 6 7 8 9 10 12 14 20 30] def /Rldbbreaks [0.2 6 10 20 30] def /Rldbdivs [0.2 0.5 1 2] def /Rcplabels [0.01 0.05 0.1 0.2 0.3 0.4 0.5 0.6 0.7 0.8 0.9 1] def /Rcpbreaks [0.005 .01 0.1 0.5 1] def /Rcpdivs [0.005 0.01 0.02 0.05] def /Rfllabels [0.1 0.2 0.4 0.6 0.8 1 1.5 2 3 4 5 6 10 15] def /Rflbreaks [0.02 0.1 0.2 2 4 6 10 15] def /Rfldivs [0.02 0.05 0.1 0.2 0.5 1 5] def /Swplabels [1.1 1.2 1.3 1.4 1.5 1.6 1.7 1.8 1.9 2 2.5 3 4 5 10] def /Swpbreaks [1.02 1.5 2 3 4 5 10] def /Swpdivs [0.02 0.05 0.1 0.2 0.5 1] def /Rclabels [0.1 0.2 0.3 0.4 0.5 0.6 0.7 0.8 0.9 1] def /Rcbreaks [0 1] def /Rcdivs [0.02] def /Tcplabels [0.99 0.95 0.9 0.8 0.7 0.6 0.5 0.4 0.3 0.2 0.1 0] def /Tcpbreaks [0.05 5 0.9 0.99 0.995] def /Tcpdivs [0.05 0.02 0.01 0.005] def /Tclabels [1 1.1 1.2 1.3 1.4 1.5 1.6 1.7 1.8 1.9 2] def /Tcbreaks [1 2] def /Tcdivs [0.02] def %* %* The following functions translate the various quantities to the %* corresponding value of rho. %* /swr-rho {dup 1 sub exch 1 add div} def % Standing-wave ratio /dbs-rho {20 div 10 exch exp swr-rho} def % 10 log (SWR) /att-rho {-10 div 10 exch exp} def % Attenuation [dB] /swl-rho {dup 1 sub exch 1 add div sqrt} def % Standing-wave loss coeff /rldb-rho {-20 div 10 exch exp} def % Return loss [dB] /rcp-rho {0 exch dup 0 ge {exch} if pop sqrt} def % Reflection coeff [dB] /tcp-rho {1 sub neg rcp-rho} def % (Trans. coeff.)^2 /rfl-rho {-10 div 10 exch exp tcp-rho} def % Reflection loss (a.k.a. % mismatch loss) [dB] /swp-rho {dup mul swr-rho} def % Standing-wave peak /tc-rho {1 sub} def % A hack :-) %***** labels brks divs qty-rho lineside direction name Donomoline - %* %* Does the nomograph line "name" according to "labels", "brks", and %* "divs", on the [left,right] side according to "direction", and on %* the [top/bottom] side according to "lineside". %* /Donomoline { /name exch def /direction exch def /lineside exch def /qty-rho exch def /divs exch def /breaks exch def /labels exch def /fullscale Unitradius direction mul def /tic 2 lineside mul def 0 0 moveto 0 2 rlineto stroke fullscale 0 moveto 0 tic rlineto stroke 0 1 divs length 1 sub {/ix exch def breaks ix get divs ix get breaks ix 1 add get { qty-rho cvx exec fullscale mul 0 moveto 0 tic rlineto stroke } for } for 0 1 labels length 1 sub { labels exch get dup qty-rho cvx exec fullscale mul 0 moveto 0 lineside 0 gt {3} {-7} ifelse rmoveto str cvs dup stringwidth pop 2 div neg 0 rmoveto show } for fullscale 0 moveto 0.05 fullscale mul 0 rlineto stroke gsave fullscale 1.05 mul 0 translate 45 direction mul rotate 0 0 moveto 0.22 fullscale mul 0 lineto stroke lineside 0 gt {3} {-3} ifelse direction mul lineside 0 gt {1} {-5} ifelse moveto direction 0 lt {name stringwidth pop neg 0 rmoveto} if name show grestore } def %***** - Donomograph - %* %* Draws all the nomograph scales, taking care of pesky "infinity" %* symbols and other asymmetries. Very tacky. %* /Donomograph { 0 setlinewidth 0 setgray /str 20 string def gsave 0 -4.0 72 mul translate 0 0 moveto (ECHELLE LINEAIRE DES PARAMETRES) dup stringwidth pop 2 div neg 0 rmoveto show 0.1 Unitradius mul -10 moveto (VERS LA CHARGE \320\>) show 0.9 Unitradius mul -10 moveto (\<\320 VERS LE GENERATEUR) dup stringwidth pop neg 0 rmoveto show 0 -0.25 72 mul translate 0 0 moveto 0 -.5 72 mul lineto stroke Unitradius neg 10 moveto 0 0.65 Unitradius mul rlineto stroke Unitradius 10 moveto 0 0.65 Unitradius mul rlineto stroke Unitradius neg 0 moveto Unitradius 0 lineto stroke Swrlabels Swrbreaks Swrdivs (swr-rho) 1 -1 (SWR) Donomoline -4 3 moveto (1) show Symfont Unitradius 3 add neg 3 moveto (\245) show Helvfont Dbslabels Dbsbreaks Dbsdivs (dbs-rho) -1 -1 (dBS) Donomoline -4 -7 moveto (1) show Symfont Unitradius 2 add neg -7 moveto (\245) show Helvfont Attlabels Attbreaks Attdivs (att-rho) 1 1 (ATTEN. [dB]) Donomoline Swllabels Swlbreaks Swldivs (swl-rho) -1 1 (S.W. LOSS COEFF) Donomoline 1 -7 moveto (1) show Symfont Unitradius 2 sub -7 moveto (\245) show Helvfont 0 -0.25 72 mul translate Unitradius neg 0 moveto Unitradius 0 lineto stroke Rldblabels Rldbbreaks Rldbdivs (rldb-rho) 1 -1 (RTN. LOSS [dB]) Donomoline Symfont -4 3 moveto (\245) show Helvfont Rcplabels Rcpbreaks Rcpdivs (rcp-rho) -1 -1 (RFL. COEFF, P) Donomoline -4 -7 moveto (0) show Rfllabels Rflbreaks Rfldivs (rfl-rho) 1 1 (RFL. LOSS [dB]) Donomoline Symfont Unitradius 1 sub 3 moveto (\245) show Helvfont 1 3 moveto (0) show Swplabels Swpbreaks Swpdivs (swp-rho) -1 1 (S.W. PEAK \(CONST. P\)) Donomoline 1 -7 moveto (0) show Symfont Unitradius 1 sub -7 moveto (\245) show Helvfont 0 -0.25 72 mul translate Unitradius neg 0 moveto Unitradius 0 lineto stroke Rclabels Rcbreaks Rcdivs () 1 -1 (RFL. COEFF, E or I) Donomoline -4 3 moveto (0) show Tcplabels Tcpbreaks Tcpdivs (tcp-rho) 1 1 (TRANSM. COEFF, P) Donomoline 1 3 moveto (1) show newpath 0 0 moveto -2 -3 lineto 2 -3 lineto 2 -3 lineto closepath fill 0 -8 moveto (CENTRE) dup stringwidth pop 2 div neg 0 rmoveto show 0 -0.25 72 mul translate Unitradius neg 0 moveto Unitradius 0 lineto stroke Tclabels Tcbreaks Tcdivs (tc-rho) 1 1 (TRANSM. COEFF, E or I) Donomoline Unitradius neg 0 translate 0 2 98 { dup Unitradius mul 0.01 mul dup 0 moveto 0 2 rlineto stroke exch dup 10 mod 0 eq {exch 3 moveto .01 mul str cvs dup stringwidth pop 2 div neg 0 rmoveto show} {pop pop} ifelse } for newpath 0 0 moveto -2 -3 lineto 2 -3 lineto closepath fill 0 -8 moveto (ORIGINE) dup stringwidth pop 2 div neg 0 rmoveto show grestore } def %***** Pointarray Zo Dodots - %* %* Dodots plots specific points on the chart. The points are supplied %* as triads of unnormalized resistance, unnormalized reactance, and %* a string label to be associated with the point. The system impedance %* is given by Zo. %* /Dodots { /znaught exch def /pointarray exch def pointarray length 3 mod 0 eq { 0 3 pointarray length 3 sub { /ix exch def pointarray ix get znaught div pointarray ix 1 add get znaught div RXtoUV Unitradius mul exch Unitradius mul exch 2 copy moveto 2 copy 3 0 360 arc currentgray 0 setgray fill setgray moveto 4 -3 rmoveto currentfont /Helvetica-Bold findfont 8 scalefont setfont pointarray ix 2 add get show setfont } for } if } def %***** title subtitle param1 ... param6 Dotitles - %* %* Prints nice titles at the top of the page. %* /Dotitles { /fontstash currentfont def /Helvetica findfont 10 scalefont setfont 1.5 72 mul 3.6 72 mul moveto show 1.5 72 mul 3.74 72 mul moveto show 1.5 72 mul 3.88 72 mul moveto show -3.5 72 mul 3.6 72 mul moveto show -3.5 72 mul 3.74 72 mul moveto show -3.5 72 mul 3.88 72 mul moveto show /Helvetica findfont 12 scalefont setfont 0 4.1 72 mul moveto dup stringwidth pop 2 div neg 0 rmoveto show /Helvetica-Bold findfont 16 scalefont setfont 0 4.4 72 mul moveto dup stringwidth pop 2 div neg 0 rmoveto show fontstash setfont } def %DoGB DoRX Docoeffcircle Dowavecircle Docircletext Donomograph (Abaque de Smith) (WA3VPZ) (Smith Draw 1.1) (Pautex JF) ( ) ( ) ( ) ( ) Dotitles % [50 -5 (100 MHz) 35 -7 (200 MHz) % 25 5 (300 MHz) 20 20 (400 MHz)] 50 Dodots grestore /#copies 1 def %* showpage